home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
ada
/
ada_met1.zip
/
EXECUTE.ADA
< prev
next >
Wrap
Text File
|
1989-06-25
|
13KB
|
387 lines
------------------------------------------------------------------------------
--
-- Separate Unit - EXECUTE
--
-- This file contains the routine EXECUTE. Given an AST
-- operator node which has its operand defined, this routine will
-- execute that operator (and any operators beneath it) and alter
-- the AST to reflect the result.
--
-- It is possible that an error will creep in and the operands will
-- not be of the appropriate types. In this case notify the user of
-- the error. If thorough type-checking were included in the parser
-- then the only way this error could arise would be through
-- variable bindings.
--
------------------------------------------------------------------------------
separate(prover)
procedure execute (operator : in out AST_ptr;
bindings : in out binding_list;
level : natural;
failed : in out boolean ) is
temp : AST_ptr := null;
is_int_1, is_int_2, use_threshold : boolean := false;
matched, unified : boolean;
int_result, trash : integer;
rcs_1, rcs_2, rcs_result : long_float; --!!! was float
radar_1, radar_2, radar_result : radar_values;
left_value, right_value : argument_ptr;
temp_bindings : binding_list;
package arg_io is new enumeration_io(argument_type); use arg_io; --!!!
package token_io is new enumeration_io(token_type ); use token_io; --!!!
package node_io is new enumeration_io(AST_node_type); use node_io; --!!!
procedure binary_arithmetic is
begin
lookup(operator.left_operand, level, bindings, left_value, trash);
lookup(operator.right_operand, level, bindings, right_value, trash);
if (left_value.is_a = integer_num) and (right_value.is_a = integer_num) then
if operator.binary_op = asterisk then
int_result := left_value.int_num * right_value.int_num;
elsif operator.binary_op = minus then
int_result := left_value.int_num - right_value.int_num;
elsif operator.binary_op = rw_mod then
int_result := left_value.int_num mod right_value.int_num;
elsif operator.binary_op = plus then
int_result := left_value.int_num + right_value.int_num;
else
int_result := left_value.int_num / right_value.int_num;
end if;
temp := new AST'(integer_num, int_result);
else
if left_value.is_a = integer_num then
rcs_1 := long_float(left_value.int_num); --!!! was float
elsif left_value.is_a = float_num then
rcs_1 := left_value.rcs_num;
else
error(no_pointer,"invalid type to arithmetic operator");
failed := true;
end if;
if right_value.is_a = integer_num then
rcs_2 := long_float(right_value.int_num); --!!! was float
elsif right_value.is_a = float_num then
rcs_2 := right_value.rcs_num;
else
error(no_pointer,"invalid type to arithmetic operator");
failed := true;
end if;
if not failed then
if operator.binary_op = asterisk then
rcs_result := rcs_1 * rcs_2;
elsif operator.binary_op = minus then
rcs_result := rcs_1 - rcs_2;
elsif operator.binary_op = rw_mod then
error(no_pointer,"'mod' only valid for integer arguments");
failed := true;
elsif operator.binary_op = plus then
rcs_result := rcs_1 + rcs_2;
else
rcs_result := rcs_1 / rcs_2;
end if;
if not failed then
temp := new AST'(float_num, rcs_result);
end if;
end if;
end if;
end binary_arithmetic;
procedure binary_logic is
begin
if operator.left_operand.node_type = radar_value then
radar_1 := operator.left_operand.radar_num;
elsif operator.left_operand.node_type = threshold_marker then
radar_1 := operator.left_operand.radar_value;
threshold := operator.left_operand.threshold;
use_threshold := true;
else
failed := true;
put("Error -- radar operator ");put(operator.binary_op);
put(" given invalid operand of type ");
put(operator.left_operand.node_type); new_line;
end if;
if operator.right_operand.node_type = radar_value then
radar_2 := operator.right_operand.radar_num;
elsif operator.right_operand.node_type = threshold_marker then
radar_2 := operator.right_operand.radar_value;
threshold := operator.right_operand.threshold;
use_threshold := true;
else
failed := true;
put("Error -- radar operator ");put(operator.binary_op);
put(" given invalid operand of type ");
put(operator.right_operand.node_type); new_line;
end if;
--
if failed then
radar_result := 0.0;
else
if operator.binary_op = bar then
--
-- The following line is an implementation of the
-- combining of two radar values
--
rcs_result := radar_1 * radar_2 - (radar_1 * radar_2);
--
-- Occasionally borderline inaccuracies in floating point
-- arithmetic cause a result greater than one, which in
-- turn causes a constraint error
--
if rcs_result > 1.0 then
radar_result := 1.0;
else
radar_result := rcs_result;
end if;
elsif operator.binary_op = comma then
if radar_1 < radar_2 then
radar_result := radar_1;
else
radar_result := radar_2;
end if;
elsif operator.binary_op = hat then
radar_result := radar_1 * radar_2;
else -- op = semicolon
if radar_1 > radar_2 then
radar_result := radar_1;
else
radar_result := radar_2;
end if;
end if;
end if;
--
if use_threshold then
temp := new AST'(threshold_marker, radar_result, threshold);
else
temp := new AST'(radar_value, radar_result);
end if;
current_truth := radar_result;
end binary_logic;
procedure binding_comparator is
begin
temp_bindings := bindings;
unify_arg(operator.left_operand, operator.right_operand, level,
level, temp_bindings, unified);
if (unified xor (operator.binary_op /= not_equal)) then
temp := new AST'(radar_value, 0.0);
current_truth := 0.0;
failed := true;
else
temp := new AST'(radar_value, 1.0);
current_truth := 1.0;
end if;
if not (operator.binary_op = not_equal) then -- save the bindings
bindings := temp_bindings;
end if;
end binding_comparator;
procedure comparator is
begin
lookup(operator.left_operand , level, bindings, left_value, trash);
lookup(operator.right_operand , level, bindings, right_value, trash);
if (left_value.is_a = right_value.is_a) or
((left_value.is_a = integer_num) and (right_value.is_a = float_num)) or
((left_value.is_a = float_num ) and (right_value.is_a = integer_num))
then
case left_value.is_a is
when predicate =>
if (operator.binary_op = equality ) or
(operator.binary_op = not_equality) then
matched := left_value.name.name = right_value.name.name;
elsif operator.binary_op = less_than then
matched := left_value.name.name < right_value.name.name;
elsif operator.binary_op = greater_than then
matched := left_value.name.name > right_value.name.name;
elsif operator.binary_op = less_or_equal then
matched := left_value.name.name <= right_value.name.name;
else -- op = greater_or_equal
matched := left_value.name.name >= right_value.name.name;
end if;
when variable =>
if (operator.binary_op = equality ) or
(operator.binary_op = not_equality) then
matched := (left_value.v_name.name = right_value.v_name.name);
else
error(no_pointer,"uninstantiated variable to <,<=,>,>=");
failed := true;
end if;
when integer_num | float_num =>
if left_value.is_a = integer_num then
rcs_1 := long_float(left_value.int_num); --!!! was float
else
rcs_1 := left_value.rcs_num;
end if;
if right_value.is_a = integer_num then
rcs_2 := long_float(right_value.int_num); --!!! was float
else
rcs_2 := right_value.rcs_num;
end if;
if (operator.binary_op = equality ) or
(operator.binary_op = not_equality) then
matched := rcs_1 = rcs_2;
elsif oper